<?php

// +----------------------------------------------------------------------
// | Wechat Plugin for ThinkAdmin
// +----------------------------------------------------------------------
// | 版权所有 2014~2023 Anyon <zoujingli@qq.com>
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库：https://gitee.com/zoujingli/think-plugs-wechat
// | github 代码仓库：https://github.com/zoujingli/think-plugs-wechat
// +----------------------------------------------------------------------

namespace app\data\service;
use think\facade\Db;
use think\admin\Exception;
use think\admin\extend\JsonRpcClient;
use think\admin\Library;
use think\admin\storage\LocalStorage;
use think\exception\HttpResponseException;
use app\data\model\DataDevice;
use app\data\model\DataCat;
use app\data\model\DataDeviceLog;
use app\data\model\DataMonitorLog;
use app\data\model\DataStatusLog;
use app\data\model\DataDeviceSettings;
use app\data\service\EventService;
use app\data\service\IotThingService;
use GatewayClient\Gateway;
class IotMsgService
{
    public function handle($command,$header,$body){
        $data = json_decode($body,true);
        //设备状态上报(设备上下线)
        if(strpos($header['topic'], 'mqtt/status')){
            $this->updateOnlineState($data,$header['topic']);
        }
        //自定义消息上报
        if(strpos($header['topic'], '/user/update')){
            $this->UserUpdate($data);
        }
        //新增/删除/设备监听
        if(strpos($header['topic'], '/thing/lifecycle')){
            $this->lifeCycleDevice($data,$header['topic']);
        }
        //OTA上报进度
        if(strpos($header['topic'], '/ota/device/progress')){
            $this->otaProgress($data,$header['topic']);
        }
        //设备属性上报
        if(strpos($header['topic'], '/thing/event/property/post')){
            $this->updateProperty($data,$header['topic']);
        }
        //警告事件
        if(strpos($header['topic'], '/thing/event/Warning/post')){
            $this->eventPost($data,'Warning');
        }
        //Info事件
        if(strpos($header['topic'], '/thing/event/Log_Post/post')){
            $this->eventPost($data,'Log_Post');
        }
        //幼猫保护触发事件
        if(strpos($header['topic'], '/thing/event/Kitten_Protect_Start/post')){
            $this->eventPost($data,'Kitten_Protect_Start');
        }
        //幼猫保护结束事件
        if(strpos($header['topic'], '/thing/event/Kitten_Protect_End/post')){
            $this->eventPost($data,'Kitten_Protect_End');
        }
        //宠物进入事件
        if(strpos($header['topic'], '/thing/event/Cat/post')){
            $this->eventPost($data,'Cat');
        }
        //数据统计上报
        if(strpos($header['topic'], '/thing/event/Parameter_Post/post')){
            $this->eventPost($data,'Parameter_Post');
        }

    }
    //事件处理
    protected function eventPost($data,$type){
       $obj_event = new EventService();
       $obj_event->set($data,$type);
    }
    //OTA上报进度
    protected function otaProgress($data,$topic){
        //测试socket推送消息
        if(Gateway::isUidOnline(3)){
            Gateway::sendToUid(3, json_encode($data));
        }
    }
    //设备上下线消息
    protected function updateOnlineState($data,$topic){
        $status = $data['status']=='online'?1:0;
        $clientIp = isset($data['clientIp'])??'';
        $check_time = DataDevice::mk()->where(['iotId'=>$data['iotId']])->value('status_update_time');
        $msg_time = timeToMilliseconds($data['time']);
        if($msg_time>$check_time){
            DataDevice::mk()->setOnline($data['iotId'],$clientIp,$status,$msg_time);
        }
        $log_data=[
            'deviceName'=>$data['deviceName'],
            'iot_id'=>$data['iotId'],
            'topic'=>$topic,
            'status_time'=>$data['time'],
            'remark'=>$status==1?'设备上线':'设备线下',
        ];
        DataStatusLog::mk()->add($log_data);
        //设备上线 推送猫咪数据给设备
        if($status == 1){
            $member_id =  DataDevice::mk()->where(['iotId'=>$data['iotId']])->value('member_id');
            $cats = DataCat::mk()->where(['member_id'=>$member_id,'is_deleted'=>0])->where('sort','>',0)->select();
            if(!empty($cats)){
                $class = new IotThingService();
                foreach($cats as $item){
                    $weight = round($item['weight']/1000, 2);
                    $avatar_thumb = $item['avatar_thumb'];
                    $avatar_thumb_f = str_replace('./', '/www/wwwroot/tatatest/public/', $avatar_thumb);
                    $data_cat=[
                        'Cat_ID'=>$item['sort'],
                        'Cat_Name'=>$item['nickname'],
                        'Cat_Weight'=>$weight,
                        'Cat_Picture_Size'=>$avatar_thumb==''?0:filesize($avatar_thumb_f),
                        'Cat_Picture'=>$avatar_thumb==''?'':config('iot.host').str_replace('./', '/', $avatar_thumb),
                        'Del_ID'=>0,
                    ];
                    $class->setService($data['iotId'],'Cat_Data',json_encode($data_cat));
                }
            }
        }
    }
    //属性上报
    protected function updateProperty($data,$topic){
        if(isset($data['items'])){
            $arr = $data['items'];
            $title = key($arr);
            if($title!= null){
                $value = $data['items'][$title]['value'];
                $time =  date('Y-m-d H:i:s',$data['items'][$title]['time']/1000);
                $this->toSocketPro($data['iotId'],$title,$value);
                //设备运行状态日志
                if($title == 'Prform_State'){
                    if($value<24){
                        $this->toPrformStateLog($data['iotId'],$value,$time); //记录服务日志
                    }
                }
                elseif($title == 'Sterilize_Deep_Stop' && $value==1){
                    $redis = redis();
                    $redis->select(1);
                    $group_id = $redis->get('group_'.$data['iotId'])??0;//当前分组ID
                    if($group_id>0){
                        $log_data=[
                            'iot_id'=>$data['iotId'],
                            'remark'=>'强制终止杀菌',
                            'level'=>1,
                            'group_id'=>$group_id,
                        ];
                        DataDeviceLog::mk()->insert($log_data);
                    }
                }
                //舱门状态
                elseif($title == 'State_Motor_Door' && $value<2){
                    $redis = redis();
                    $redis->select(1);
                    $group_id = $redis->get('group_'.$data['iotId'])??0;//当前分组ID
                    $redis_status = $redis->get($data['iotId']); // 上一次的设备状态
                    if($group_id>0 && $redis_status>0){
                        $log_data=[
                            'iot_id'=>$data['iotId'],
                            'remark'=>'舱门'.($value==0?'关闭':'开启'),
                            'level'=>1,
                            'group_id'=>$group_id,
                            //  'create_at' =>$time
                        ];
                        DataDeviceLog::mk()->insert($log_data);
                    }

                }
                //集便仓状态
                elseif($title == 'Light')
                {
                        if (isset($value['Mode'])){
                            $arr = [
                                '1'=>'科技蓝',
                                '2'=>'科技粉',
                                '3'=>'科技白',
                                '4'=>'薄荷绿',
                                '5'=>'紫罗兰',
                                '6'=>'清新黄',
                                '7'=>'毒液绿',
                                '8'=>'粉紫色',
                                '9'=>'冰湖蓝',
                                '10'=>'自定义颜色',
                            ];
                            $remark =  '灯光切换为'.($arr[$value['Mode']]);
                            $check = DataDeviceLog::mk()->where(['remark'=>$remark,'iot_id'=>$data['iotId']])->order('id desc')->find();
                            if(empty($check)){
                                $log_data=[
                                    'iot_id'=>$data['iotId'],
                                    'remark'=>$remark
                                ];
                                DataDeviceLog::mk()->insert($log_data);
                            }
                        }

                    }
                //集便仓状态
                elseif($title == 'State_Bin'){
                    $log_data=[
                        'iot_id'=>$data['iotId'],
                        'remark'=>($value==0?'集便仓已锁止':'集便仓已弹出'),
                        'level'=>1,
                        'group_id'=>0,
                        //  'create_at' =>$time
                    ];
                    DataDeviceLog::mk()->insert($log_data);

                }
                //杀菌状态变化日志
                elseif(in_array($title,['Ozone_Sterilize','Plasma_Sterilize','Atomize_Sterilize'])){
                    $title_arr =  config('errorcode.sterilize');
                    $title_str = $title_arr[$title];
                    $redis = redis();
                    $redis->select(1);
                    $group_id = $redis->get('group_'.$data['iotId'])??0;//当前分组ID
                    if($group_id>0 && $value == 1){
                        $log_data=[
                            'iot_id'=>$data['iotId'],
                          //  'remark'=>$title_str.($value==1?'开始':'结束'),
                            'remark'=>$title_str.'开始工作',//杀菌只显示开始
                            'level'=>1,
                            'group_id'=>$group_id,
                            // 'create_at' =>$time
                        ];
                        DataDeviceLog::mk()->insert($log_data);
                    }

                }
            }
        }

    }
    protected function toPrformStateLog($iotId,$status,$time){
        $index_array=[0,1,2,3,4,5,7,8,9,10,11,12,13,14,15,18,23,19];
        if (in_array($status,$index_array))
        {
            $redis = redis();
            $redis->select(1);
            $remark_arr = config('errorcode.info');
            $redis_status = $redis->get($iotId); // 上一次的设备状态
            $group_id = $redis->get('group_'.$iotId)??0;//当前分组ID
            if($status>0 && $status<10){
                $remark = $redis_status == $status?'继续':$remark_arr[$status];
                //开始/继续操作
                if($status == 3){
                    //自动清理,特殊处理
                    if($redis->exists('cat_log_'.$iotId)){
                        $json_data = $redis->get('cat_log_'.$iotId);
                        $log_data=json_decode($json_data,true);
                        $log_data['group_id']=$group_id;
                        $redis->del('cat_log_'.$iotId);
                    }else{
                        $log_data=[
                            'iot_id'=>$iotId,
                            'remark'=>$remark,
                            'group_id'=>$group_id,
                        ];
                    }
                }else{
                    $log_data=[
                        'iot_id'=>$iotId,
                        'remark'=>$remark,
                        'group_id'=>$group_id,
                    ];
                }
                $group_id_new = DataDeviceLog::mk()->insertGetId($log_data);
                $redis->set($iotId, $status);//把当前设备状态存入REDIS
                //如果$redis_status状态存在说明是暂停后继续的，如果不存在则是直接执行
                if($redis_status == 0 || $redis_status==''){
                    $redis->set('group_'.$iotId, $group_id_new);
                }
            }elseif($status>=10 && $status<=15){
                //状态10-15暂停
                $log_data=[
                    'iot_id'=>$iotId,
                    'remark'=>'暂停',
                    'group_id'=>$group_id,
                ];
                DataDeviceLog::mk()->insertGetId($log_data);
                //$redis->set($iotId, $status);//把状态存入REDIS
            }elseif($status == 18){
                $log_data=[
                    'iot_id'=>$iotId,
                    'remark'=>$remark_arr[$status],
                    'group_id'=>0,
                ];
                DataDeviceLog::mk()->insertGetId($log_data);
                $redis->set($iotId, $status);//把状态存入REDIS
            }elseif($status == 19 || $status == 23){
                $redis->set($iotId, $status);//把状态存入REDIS
            }elseif($status == 0){
                //结束上一次的程序
                $remark_arr_end = config('errorcode.info_end');
                $group_id = $redis->get('group_'.$iotId)??0;//当前分组ID

                if($redis_status == 19 || $redis_status ==23){
                    log_result($redis_status.'='.$group_id,'stop.txt');
                }
                if($redis_status!='' && $redis_status>0){
                    //获取上一次的状态
                    $log_data=[
                        'iot_id'=>$iotId,
                        'remark'=>$group_id>0?'已完成':$remark_arr_end[$redis_status],
                        'level'=>1,
                        'group_id'=>$group_id,
                    ];
                    DataDeviceLog::mk()->insert($log_data);
                }
                $redis->del('group_'.$iotId);
                $redis->del($iotId);
            }

        }

    }
    // 同步温度 雾化液
    protected function toSocketPro($iotId,$title,$value){
        $uid = DataDevice::mk()->where(['iotId'=>$iotId])->value('member_id');
        $data=[
            'iotId'=>$iotId,
            'type'=>'pro',
            'title'=>$title,
            'value'=>$value
        ];
        if(Gateway::isUidOnline($uid)){
            Gateway::sendToUid($uid, json_encode($data));
        }
    }
    protected function UserUpdate($data){
        //echo "UserUpdate";
    }
    protected function lifeCycleDevice($data,$topic){
        $remark ='';
        if($data['action'] == 'create'){
            $remark = '新增设备';
            $params=[
                'iotId'=>$data['iotId'],
                'deviceName'=>$data['deviceName'],
                'deviceSecret'=>$data['deviceSecret'],
                'productKey'=>$data['productKey'],
                'nickname'=>isset($data['nickname'])??'',
            ];
            $check =  DataDevice::mk()->where(['iotId'=>$params['iotId']])->count();
            if($check == 0){
                DataDevice::mk()->add($params);
            }
        }
        if($data['action'] == 'delete'){
            $remark = '删除设备';
            DataDevice::mk()->del($data['iotId']);
        }
        //禁用
        if($data['action'] == 'disable'){
            $remark = '禁用设备';
            DataDevice::mk()->setStatus($data['iotId'],-2);
        }
        //启用
        if($data['action'] == 'enable'){
            $remark = '启用设备';
            DataDevice::mk()->setStatus($data['iotId'],1);
        }
        //插入日志
//        $log_data=[
//            'deviceName'=>$data['deviceName'],
//            'iot_id'=>$data['iotId'],
//            'topic'=>$topic,
//            'remark'=>$remark,
//        ];
//        DataMonitorLog::mk()->add($log_data);
    }
}
